package com.iwhalecloud.bss.kite.cucc.service.util;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.iwhalecloud.bss.kite.common.constant.ErrorConsts;
import com.iwhalecloud.bss.kite.common.util.JsonUtils;
import com.iwhalecloud.bss.kite.common.util.KiteMapUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.common.util.PageInfoUtils;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalInfConsts;
import com.iwhalecloud.bss.kite.dataservice.cache.DcPublicCache;
import com.iwhalecloud.bss.kite.dataservice.cache.DcSystemParamCache;
import com.iwhalecloud.bss.kite.dataservice.entity.DcPublic;
import com.ztesoft.bss.common.exception.BssException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;

/**
 * 功能描述：Token生成方法
 *
 * @author yang.kuowei
 * @version 1.0
 * @date 2020/02/18 17:08
 */
public class LocalTokenUtil {
    //i租机提供-系统编码
    private static final String SYSTEM_CODE = "crm";

    //i租机提供-共享秘钥
    private static final String SHARED_KEY = "HYfIoQePf2Qirano";

    //i租机提供-私钥
    private static final String DES_KEY = "xG4wfzVWDu553LAq";

    private static final Logger LOGGER = LoggerFactory.getLogger(LocalTokenUtil.class);
    /**
     * 生成token方法
     */
    public static String getToken() {
        List<DcPublic> publics = DcPublicCache.getByPcode("20170919", "cloud_rent_machine", "config");
        String strToken = "";
        DesUtils desUtil = null;
        String str = "";
        //根据需求将数据配置进dc_public，若为空则用默认原有的常量
        if (!publics.isEmpty()) {
            DcPublic config = publics.get(0);
            String currentTime = System.currentTimeMillis() / 1000 + "";    //时间戳秒数
            String md5Info = MD5Util.getMD5Code("" + config.getCodea() + config.getCodeb() + currentTime);
            str = md5Info + ";" + config.getCodea() + ";" + currentTime;
            desUtil = new DesUtils("" + config.getCodec());
        }
        else {
            String currentTime = System.currentTimeMillis() / 1000 + "";    //时间戳秒数
            String md5Info = MD5Util.getMD5Code(SYSTEM_CODE + SHARED_KEY + currentTime);
            str = md5Info + ";" + SYSTEM_CODE + ";" + currentTime;
            desUtil = new DesUtils(DES_KEY);
        }
        try {
            strToken = desUtil.encrypt(str);
        }
        catch (Exception e) {
            LOGGER.error(e.getMessage());
        }
        return strToken;
    }
    public static void main(String[] args) throws Exception{
//        String appSecret= "5SUGS89crs9TlfeLbucPf8q814XJYFK";//生产
//        String appSecret= "HegywP1dDzHAWuXMIJNDtTN9a272oEQy";//测试
        String appSecret = DcSystemParamCache.get("ORDER_APPSECRET").getParamVal();
        String appId= "XAkrsbpYlL";
        String timestamp = getDate_yyyy_MM_ddHHmmssSSS();
        String transId = getDate_yyyyMMddHHmmssSSS()+randomNum(6);
        String tokenStr = "APP_ID"+ appId+"TIMESTAMP"+timestamp+"TRANS_ID"+ transId+appSecret;
        String token = encoderByMd5(tokenStr);
        System.out.println("\"APP_ID\":\""+appId+"\",");
        System.out.println("\"TIMESTAMP\":\""+timestamp+"\",");
        System.out.println("\"TRANS_ID\":\""+transId+"\",");
        System.out.println("\"TOKEN\":\""+token+"\"");
    }


    public static String getTokenNew() {
        String appSecret = DcSystemParamCache.get("ORDER_APPSECRET").getParamVal();
        String appId= "5UPmcd0ARr";
        String timestamp = getDate_yyyy_MM_ddHHmmssSSS();
        String transId = getDate_yyyyMMddHHmmssSSS()+randomNum(6);
        String tokenStr = "APP_ID"+ appId+"TIMESTAMP"+timestamp+"TRANS_ID"+ transId+appSecret;
        String token = null;
        try {
            token = encoderByMd5(tokenStr);
        }catch (Exception e){
            throw new RuntimeException(e.getCause());
        }
        return token;
    }

    public static String  encoderByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        //确定计算方法
        MessageDigest md5=MessageDigest.getInstance("MD5");
        md5.update((str).getBytes("UTF-8"));
        byte b[] = md5.digest();
        int i;
        StringBuffer buf = new StringBuffer("");
        for(int offset=0; offset<b.length; offset++){
            i = b[offset];
            if(i<0){
                i+=256;
            }
            if(i<16){
                buf.append("0");
            }
            buf.append(Integer.toHexString(i));
        }
        String result = buf.toString();
        return result;
    }

    public static String getDate_yyyy_MM_ddHHmmssSSS() {
        Date d = new Date();
        SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String dateString = df1.format(d);
        return dateString;
    }
    public static String getDate_yyyyMMddHHmmssSSS() {
        Date d = new Date();
        SimpleDateFormat df1 = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String dateString = df1.format(d);
        return dateString;
    }
    /**
     * 生成 n位 随机数
     * @param n
     * @return
     */
    public  static String randomNum(int n) {
        Random random = new Random();
        String result="";
        for (int i=0;i<n;i++)
        {
            result+=random.nextInt(10);
        }
        return result;
    }

    public static Map<String, String> getHeaderMap(){
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Content-Type","application/json; charset=UTF-8");
        headerMap.put("Accept","application/json");
        headerMap.put("Accept-Encoding","");
        return headerMap;
    }

    public static Map<String, Object> getParamMap(Map<String, Object> bodyMap){
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("UNI_BSS_BODY",bodyMap);
        Map<String, Object> uniBssHead = new HashMap<>();
        String appSecret = DcSystemParamCache.get("ORDER_APPSECRET").getParamVal();
        String timestamp = getDate_yyyy_MM_ddHHmmssSSS();
        String transId = getTransId();
        String tokenStr = "APP_ID" + LocalInfConsts.APP_ID + "TIMESTAMP" + timestamp + "TRANS_ID" + transId + appSecret;
        String token = null;
        try {
            token = encoderByMd5(tokenStr);
        }catch (Exception e){
            throw new RuntimeException(e.getCause());
        }
        uniBssHead.put("APP_ID", LocalInfConsts.APP_ID);
        uniBssHead.put("TIMESTAMP",timestamp);
        uniBssHead.put("TRANS_ID", transId);
        uniBssHead.put("TOKEN",token);
        paramMap.put("UNI_BSS_HEAD", uniBssHead);

        Map<String, Object> uniBssAttached = new HashMap<>();
        uniBssAttached.put("MEDIA_INFO","");
        paramMap.put("UNI_BSS_ATTACHED", uniBssAttached);

        return paramMap;
    }

    public static String getTransId() {
        return KiteStringUtils.join(getDate_yyyyMMddHHmmssSSS(), randomNum(6));
    }

    /**
     * 调用能开接口返回参数校验并处理（返回对象）
     * @param result
     * @param rspKey
     * @param targetClass
     * @return
     */
    public static <T> T checkRespParamAndGetObject(String result, String rspKey, Class<T> targetClass) {
        JSONObject resultObject = JsonUtils.parseObject(result);
        JSONObject uniBssHead = KiteMapUtils.getValue(resultObject, "UNI_BSS_HEAD");
        if (!KiteStringUtils.equals(KiteMapUtils.getString(uniBssHead, "RESP_CODE"), LocalInfConsts.RESP_SUCCESS)) {
            ErrorConsts.INF_INVOKE_EXCEPTION.throwOut("",KiteMapUtils.getString(uniBssHead, "RESP_DESC"));
        }
        JSONObject uniBssBody = KiteMapUtils.getValue(resultObject, "UNI_BSS_BODY");
        if (KiteMapUtils.isEmpty(uniBssBody)) {
            ErrorConsts.INF_INVOKE_EXCEPTION.throwOut("","返回报文缺少UNI_BSS_BODY节点");
        }
        T object = JsonUtils.parseObject(Optional.ofNullable(KiteMapUtils.getValue(uniBssBody, rspKey)).orElse("").toString(), targetClass);
        return object;
    }

    /**
     * 调用能开接口返回参数校验并处理（返回集合）
     * @param result
     * @param rspKey
     * @param targetClass
     * @return
     */
    public static <T> List<T> checkRespParamAndGetDataList(String result, String rspKey, Class<T> targetClass) {
        JSONObject resultObject = JsonUtils.parseObject(result);
        JSONObject uniBssHead = KiteMapUtils.getValue(resultObject, "UNI_BSS_HEAD");
        if (!KiteStringUtils.equals(KiteMapUtils.getString(uniBssHead, "RESP_CODE"), LocalInfConsts.RESP_SUCCESS)) {
            ErrorConsts.INF_INVOKE_EXCEPTION.throwOut("",KiteMapUtils.getString(uniBssHead, "RESP_DESC"));
        }
        JSONObject uniBssBody = KiteMapUtils.getValue(resultObject, "UNI_BSS_BODY");
        if (KiteMapUtils.isEmpty(uniBssBody)) {
            ErrorConsts.INF_INVOKE_EXCEPTION.throwOut("","返回报文缺少UNI_BSS_BODY节点");
        }
        JSONObject rspMap = KiteMapUtils.getValue(uniBssBody, rspKey);
        if (!KiteStringUtils.equals(KiteMapUtils.getString(rspMap, "RESULT_CODE"), LocalInfConsts.UNI_BSS_BODY_RESULT_SUCCESS)) {
            ErrorConsts.INF_INVOKE_EXCEPTION.throwOut("",KiteMapUtils.getString(rspMap, "RESULT_MSG"));
        }
        List<T> list = JsonUtils.parseArray(Optional.ofNullable(KiteMapUtils.getValue(rspMap, "DATA_LIST")).orElse("").toString(), targetClass);
        return list;
    }

    /**
     * 调用能开接口返回参数校验并处理（返回集合并分页）
     * @param result
     * @param rspKey
     * @param targetClass
     * @return
     */
    public static <T> PageInfo<T> checkRespParamAndGetDataListPage(String result, String rspKey, Class<T> targetClass, Integer pageSize, Integer pageNum) {
        JSONObject resultObject = JsonUtils.parseObject(result);
        JSONObject uniBssHead = KiteMapUtils.getValue(resultObject, "UNI_BSS_HEAD");
        if (!KiteStringUtils.equals(KiteMapUtils.getString(uniBssHead, "RESP_CODE"), LocalInfConsts.RESP_SUCCESS)) {
            ErrorConsts.INF_INVOKE_EXCEPTION.throwOut("",KiteMapUtils.getString(uniBssHead, "RESP_DESC"));
        }
        JSONObject uniBssBody = KiteMapUtils.getValue(resultObject, "UNI_BSS_BODY");
        if (KiteMapUtils.isEmpty(uniBssBody)) {
            ErrorConsts.INF_INVOKE_EXCEPTION.throwOut("","返回报文缺少UNI_BSS_BODY节点");
        }
        JSONObject rspMap = KiteMapUtils.getValue(uniBssBody, rspKey);
        if (!KiteStringUtils.equals(KiteMapUtils.getString(rspMap, "RESULT_CODE"), LocalInfConsts.UNI_BSS_BODY_RESULT_SUCCESS)) {
            ErrorConsts.INF_INVOKE_EXCEPTION.throwOut(KiteMapUtils.getString(rspMap, "RESULT_MSG"));
        }
        List<T> list = JsonUtils.parseArray(Optional.ofNullable(KiteMapUtils.getValue(rspMap, "DATA_LIST")).orElse("").toString(), targetClass);
        Integer total = null;
        if (Objects.nonNull(KiteMapUtils.getValue(rspMap, "TOTAL_ROW"))) {
            total = KiteMapUtils.getValue(rspMap, "TOTAL_ROW");
        }
        else {
            total = list.size();
        }
        return PageInfoUtils.coverToPageTotal(list, pageNum, pageSize, total);
    }

    public static Map<String, Object> getParamMapLowerCase(Map<String, Object> bodyMap){
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("uniBssBody",bodyMap);
        Map<String, Object> uniBssHead = new HashMap<>();
        String appSecret = DcSystemParamCache.get("ORDER_APPSECRET").getParamVal();
        String timestamp = getDate_yyyy_MM_ddHHmmssSSS();
        String transId = getTransId();
        String tokenStr = "APP_ID" + LocalInfConsts.APP_ID + "TIMESTAMP" + timestamp + "TRANS_ID" + transId + appSecret;
        String token = null;
        try {
            token = encoderByMd5(tokenStr);
        }catch (Exception e){
            throw new RuntimeException(e.getCause());
        }
        uniBssHead.put("appId", LocalInfConsts.APP_ID);
        uniBssHead.put("timestamp",timestamp);
        uniBssHead.put("transId", transId);
        uniBssHead.put("token",token);
        paramMap.put("uniBssHead", uniBssHead);
        Map<String, Object> uniBssAttached = new HashMap<>();
        uniBssAttached.put("mediaInfo","");
        paramMap.put("uniBssAttached", uniBssAttached);
        return paramMap;
    }
}
